package com.example.apigateway;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

/**
 * 参考spring cloud gateway 内置工厂RemoteAddrRoutePredicateFactory 自定义的路由断言工厂类,要求有两个 1 名字必须是
 * 配置+RoutePredicateFactory 2 必须继承AbstractRoutePredicateFactory<配置类>
 */
@Component
@Slf4j
public class AgeRoutePredicateFactory
    extends AbstractRoutePredicateFactory<AgeRoutePredicateFactory.Config> {

  public AgeRoutePredicateFactory() {
    super(AgeRoutePredicateFactory.Config.class);
  }

  /**
   * 用于从配置文件中获取参数值赋值到配置类中的属性上
   *
   * @return
   */
  @Override
  public List<String> shortcutFieldOrder() {
    // 这里的顺序要跟配置文件中的参数顺序一致
    return Arrays.asList("minAge", "maxAge");
  }

  /**
   * 断言逻辑
   *
   * @param config
   * @return
   */
  @Override
  public Predicate<ServerWebExchange> apply(AgeRoutePredicateFactory.Config config) {
    return new Predicate<ServerWebExchange>() {
      @Override
      public boolean test(ServerWebExchange serverWebExchange) {
        // 1 接收前台传入的age参数
        String ageStr = serverWebExchange.getRequest().getQueryParams().getFirst("age");

        // 2 先判断是否为空
        if (StringUtils.isNotEmpty(ageStr)) {
          // 3 如果不为空,再进行路由逻辑判断
          int age = Integer.parseInt(ageStr);
          if (age < config.getMaxAge() && age > config.getMinAge()) {
            return true;
          } else {
            return false;
          }
        }
        return false;
      }
    };
  }

  /** 这个内部类，主要是用来接收配置文件中的参数 */
  public static class Config {
    private int minAge;
    private int maxAge;

    public Config() {}

    public int getMinAge() {
      return minAge;
    }

    public void setMinAge(int minAge) {
      this.minAge = minAge;
    }

    public int getMaxAge() {
      return maxAge;
    }

    public void setMaxAge(int maxAge) {
      this.maxAge = maxAge;
    }
  }
}
